package com.cxyd.modules.wms.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cxyd.common.Utils.BeanUtils;
import com.cxyd.common.constant.Constant;
import com.cxyd.common.exception.RootException;
import com.cxyd.common.page.PageData;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ConvertUtils;
import com.cxyd.common.utils.Result;
import com.cxyd.modules.core.service.SerialNumberService;
import com.cxyd.modules.sys.service.SysUserService;
import com.cxyd.modules.wms.dao.OrderBakDao;
import com.cxyd.modules.wms.dao.OrderDao;
import com.cxyd.modules.wms.dao.OrderDetailBakDao;
import com.cxyd.modules.wms.dao.OrderDetailDao;
import com.cxyd.modules.wms.dto.InterfaceMesDetailsDTO;
import com.cxyd.modules.wms.dto.OrderDTO;
import com.cxyd.modules.wms.dto.SupplierDTO;
import com.cxyd.modules.wms.entity.*;
import com.cxyd.modules.wms.excel.easy.OrderEasyExcel;
import com.cxyd.modules.wms.excel.listener.OrderExcelListener;
import com.cxyd.modules.wms.service.OrderDetailService;
import com.cxyd.modules.wms.service.OrderService;
import com.cxyd.modules.wms.service.SpuService;
import com.cxyd.modules.wms.service.SupplierService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 出库主单
 *
 * @author g_Cycle gengruyi01@163.com
 * @since 1.0.0 2023-04-27
 */
@Service
public class OrderServiceImpl extends CrudServiceImpl<OrderDao, OrderEntity, OrderDTO> implements OrderService {
    @Resource
    private OrderDetailService detailService;
    @Resource
    private SysUserService userService;
    @Resource
    private SerialNumberService serialNumberService;
    @Resource
    private SupplierService supplierService;
    @Resource
    private OrderDao orderDao;
    @Resource
    private OrderDetailDao orderDetailDao;
    @Resource
    private OrderBakDao orderBakDao;
    @Resource
    private OrderDetailBakDao orderDetailBakDao;
    @Resource
    private OrderDetailService orderDetailService;
    @Resource
    @Lazy
    private OrderService orderService;
    @Resource
    private SpuService spuService;

    @Override
    public PageData<OrderDTO> page(Map<String, Object> params) {
        //1.查询主单信息
        IPage<OrderEntity> page = baseDao.selectViewPage(
                getPage(params, "", false),
                getWrapper(params)
        );
        return getPageData(page, OrderDTO.class);
    }

    @Override
    public QueryWrapper<OrderEntity> getWrapper(Map<String, Object> params) {
        String id = (String) params.get("orderId");
        String orderNo = (String) params.get("orderNo");
        String orderSt = (String) params.get("orderSt");


        QueryWrapper<OrderEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(id), "order_id", id);
        wrapper.eq(StringUtils.isNotBlank(orderNo), "order_no", orderNo);
        wrapper.eq(StringUtils.isNotBlank(orderSt), "order_st", orderSt);
//        //新增排序
//        wrapper.orderBy(true, true, "(CASE 'order_st' " +
//                "WHEN 0 THEN 0 " +
//                "WHEN 1 THEN 1 " +
//                "WHEN 2 THEN 2 " +
//                "WHEN 9 THEN 3 " +
//                "ELSE 4 END)");
//        wrapper.orderBy(true, true, "'create_date'");
        return wrapper;
    }

    @Override
    public void save(OrderDTO dto) {
        //2.将dto转换为单据实体类
        OrderEntity entity = ConvertUtils.sourceToTarget(dto, OrderEntity.class);
        entity.setOrderType("领料出库");
        //        获取供应商信息
        SupplierDTO supplier = supplierService.getSupplierByCode(dto.getSupplierCode());
        if (supplier != null) {
            entity.setSupplierName(supplier.getSupplierName());
        }
        //4.将数据写入数据库
        insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(@RequestBody Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            deleteOrderById(ids[i]);
        }
    }

    public void deleteOrderById(Long id) {
        OrderEntity entity = baseDao.selectById(id);
        //判断明细状态是否为初始状态
        if (entity.getOrderSt() == 1 || entity.getOrderSt() == 2 || entity.getOrderSt() == 3) {
            throw new RootException("只有[初始]状态和[出库完成]的主单才可以删除！");
        }
        //删除此单据下的所有明细
        List<OrderDetailEntity> list = orderDetailService.findByOrderId(id);
        for (OrderDetailEntity orderDetailEntity : list) {
            orderDetailService.deleteById(orderDetailEntity.getDetailId());
        }
        //删除
        baseDao.deleteById(id);
    }

    @Override
    public String getOrderStById(Long id) {

        if (id == null || id.longValue() == 0) {
            return "unknown";
        }
        OrderEntity entity = baseDao.selectById(id);

        return entity.getOrderSt().toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result importOrder(String zllbh, List<InterfaceMesDetailsDTO> details) {
        if (StringUtils.isBlank(zllbh)) {
            return new Result().error("领料单号不能为空");
        }
        if (details == null) {
            return new Result().error("领料信息不能为空");
        }
        List<OrderDetailEntity> entities = ConvertUtils.sourceToTarget(details, OrderDetailEntity.class);
        int rows = orderInsert(zllbh, entities);
        if (rows > 0) {
            return new Result().ok("");
        }
        return new Result().error("领料单写入WMS系统失败!");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadFile(MultipartFile file) {
        OrderExcelListener orderExcelListener = new OrderExcelListener(orderService, orderDetailService, spuService);
        try {
            EasyExcel.read(file.getInputStream(), OrderEasyExcel.class, orderExcelListener).sheet().doRead();
        } catch (IOException e) {
            throw new RootException("文件读取失败！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void backUp(Date date, Integer num) {
        while (true) {
            List<OrderEntity> orderEntities = orderDao.selectForBackup(date, num);
            if (CollectionUtils.isEmpty(orderEntities)) {
                break;
            }
            List<OrderBakEntity> list = new ArrayList<>();
            for (OrderEntity order : orderEntities) {
                OrderBakEntity orderBak = new OrderBakEntity();
                BeanUtils.copyProperties(order, orderBak);
                list.add(orderBak);
            }
            orderBakDao.batchInsert(list);
            List<Long> ids = orderEntities.stream().map(OrderEntity::getOrderId).collect(Collectors.toList());
            orderDao.deleteBatchIds(ids);
        }
        while (true) {
            List<OrderDetailEntity> orderDetailEntities = orderDetailDao.selectForBackup(date, num);
            if (CollectionUtils.isEmpty(orderDetailEntities)) {
                break;
            }
            List<OrderDetailBakEntity> list = new ArrayList<>();
            for (OrderDetailEntity orderDetail : orderDetailEntities) {
                OrderDetailBakEntity orderDetailBak = new OrderDetailBakEntity();
                BeanUtils.copyProperties(orderDetail, orderDetailBak);
                list.add(orderDetailBak);
            }
            orderDetailBakDao.batchInsert(list);
            List<Long> ids = orderDetailEntities.stream().map(OrderDetailEntity::getDetailId).collect(Collectors.toList());
            orderDetailDao.deleteBatchIds(ids);
        }
    }

    @Override
    public OrderEntity findByOrderNo(String orderNo) {
        QueryWrapper<OrderEntity> qw = new QueryWrapper<>();
        qw.lambda().eq(OrderEntity::getOrderNo, orderNo);
        return baseDao.selectOne(qw);
    }

    public int orderInsert(String zllbh, List<OrderDetailEntity> entities) {
        //生成出库主单
        String orderNo = serialNumberService.getSerialNumberByCode("order");
        OrderEntity order = new OrderEntity();
        order.setOrderNo(orderNo);
        order.setOrderType("REQ_OT");
        order.setCreator(Constant.ClientCode.MES.getId());
        order.setUpdater(Constant.ClientCode.MES.getId());
        insert(order);
        //生成出库明细
        entities.stream().forEach(item -> {
            item.setOrderId(order.getOrderId());
            item.setCreator(Constant.ClientCode.MES.getId());
            item.setUpdater(Constant.ClientCode.MES.getId());
        });
        return detailService.batchSave(entities);
    }
}